package chapter04.part02;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;

/**
 * 半关闭
 * 
 * 场景: 向服务器传输未知大小的数据 传输中断时 需要暂时关闭 socket 的流
 * 方案: 使用半关闭 服务端暂停输出 但仍可接受数据
 * 
 * @author insight
 * @since 2021/8/29
 */
public class HalfClose {
    public static void main(String[] args) {
        new Thread(new ServerThread()).start();
        new Thread(new ClientThread()).start();
    }

    static class ServerThread implements Runnable {
        @Override
        public void run() {
            try (ServerSocket serverSocket = new ServerSocket(8080)) {
                System.out.println("ServerSocket Created Successfully...");
                try (Socket incoming = serverSocket.accept()) {
                    System.out.println("Successfully Connected to ServerSocket...");
                    try (Scanner in = new Scanner(incoming.getInputStream(),
                            StandardCharsets.UTF_8);
                         PrintWriter out = new PrintWriter(
                                 new OutputStreamWriter(incoming.getOutputStream(), StandardCharsets.UTF_8), true)) {
                        boolean online = true;
                        // 调用shutdownOutput()后 hasNextLine()自动返回false
                        while (online && in.hasNextLine()) {
                            String command = in.nextLine();
                            String content = "Echo: " + command;
                            System.out.println(command);
                            out.println(content);
                            if ("exit".equals(command.trim().toLowerCase())) {
                                online = false;
                                out.println("GoodBye");
                            }
                        }

                        System.out.println("Disconnect From ServerSocket...");
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    static class ClientThread implements Runnable {
        @Override
        public void run() {
            try (Socket socket = new Socket(InetAddress.getLocalHost(), 8080);
                 Scanner in = new Scanner(socket.getInputStream(),
                         StandardCharsets.UTF_8);
                 PrintWriter out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8))) {
                System.out.println(socket.getLocalAddress());
                out.println("1");
                out.println("2");
                out.println("3");
                out.flush();

                // 不知道要写多少 那就写完一部分先关闭输出流
                // 相当于告诉服务器 发送数据结束 EOF
                socket.shutdownOutput();

                // 接收服务器返回的数据
                while (in.hasNextLine()) {
                    String line = in.nextLine();
                    System.out.println(line);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
}